package org.openapi.parser;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.openapi.common.ApiException;
import org.openapi.consts.DirectiveConst;
import org.openapi.vo.RelData;
import org.openapi.vo.TableData;
import org.openapi.vo.TableQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 数据新增示例 POST请求
 *  {
 *      "USER": { //主数据示例
 *          "account":"admin",
 *          "name":"管理员",
 *          "phone":"13345436576",
 *          "sex":"1",
 *          "age": 25
 *      },
 *      "DETAIL":{ //扩展数据
 *         "email":"admin@qq.com",
 *         "address":"地址",
 *         "birthday":"2000-02-01"
 *         "@id":"USER.id" //用主数据主键填充
 *      },
 *      "@tag":["USER", "DETAIL"] //数据的保存顺序
 *  }
 */

/**
 * 数据更新示例 PUT请求，PATCH请求
 *  {
 *      "USER": { //主数据示例
 *          "id":1,
 *          "account":"admin",
 *          "name":"管理员",
 *          "phone":"13345436576",
 *          "sex":"1",
 *          "age": 25
 *      },
 *      "DETAIL":{ //扩展数据
 *         "email":"admin@qq.com",
 *         "address":"地址",
 *         "birthday":"2000-02-01"
 *         "userId":"@USER.id" //用主数据主键填充
 *      },
 *      "@tag":["USER", "DETAIL"] //数据的保存顺序
 *  }
 */

/**
 * 主从数据更新示例，PATCH请求，关联数据无主键就新增，有主键更新，可以在主模型User上配置事件，更新前删除PRODUCT中相关数据
 *  {
 *      "USER": { //主数据示例
 *          "id":1,
 *          "account":"admin",
 *          "name":"管理员",
 *          "phone":"13345436576",
 *          "sex":"1",
 *          "age": 25
 *      },
 *      "PRODUCT":[{ //扩展数据1
 *         "email":"admin@qq.com",
 *         "address":"地址",
 *         "birthday":"2000-02-01"
 *         "userId":"@USER.id" //用主数据主键填充
 *          },{ //扩展数据2
 *         "email":"admin@qq.com",
 *         "address":"地址",
 *         "birthday":"2000-02-01"
 *         "userId":"@USER.id" //用主数据主键填充
 *       }],
 *      "@tag":["USER", "PRODUCT"] //数据的保存顺序
 *      "@ignore":1 //有该标签会忽略全部事件
 *  }
 *
 */

/**
 * 数据删除示例 DELETE请求
 *  {
 *      "USER": { //主数据示例
 *          "id":1,
 *      },
 *      "DETAIL":{ //扩展数据
 *         "userId":"1" //用主数据主键填充
 *      },
 *      "@tag":["USER", "DETAIL"] //数据的保存顺序
 *  }
 */
public class DataParser {

    private static final Logger log = LoggerFactory.getLogger(QueryParser.class);

    /**
     * 解析更新或新增的数据
     * @param paramStr
     * @return
     */
    public static RelData parseData(String paramStr){
        JSONObject params = JSONObject.parseObject(paramStr);
        RelData data = new RelData();
        data.setTags(params.getJSONArray(DirectiveConst.TAGS).stream().map(d->d.toString()).collect(Collectors.toList()));
        data.setIgnore(params.containsKey(DirectiveConst.IGNORE));

        for(String k:data.getTags()){
            Object v = params.get(k);
            if(v instanceof JSONArray){
                JSONArray sub = (JSONArray)v;
                for(int i=0;i<sub.size();i++){
                    data.addTable(parseTable(k , sub.getJSONObject(i)));
                }
            }else if(v instanceof JSONObject){
                data.addTable(parseTable(k , (JSONObject)v));
            }else{
                throw new ApiException("数据格式不对: " + k +"  = " + params.getString(k));
            }
        }
        return data;
    }

    /**
     * 解析一张表的数据
     * @param tableName
     * @param tableParam
     * @return
     */
    public static TableData parseTable(String tableName, JSONObject tableParam){
        TableData table = new TableData();
        table.setTable(tableName);
        for(String p:tableParam.keySet()){
            Object v = tableParam.get(p);
            if(v == null){
                continue;
            }
            // SCHEMA
            if(DirectiveConst.SCHEMA.equalsIgnoreCase(p)){
                table.setSchema(v.toString());;
            }if(DirectiveConst.NULL.equalsIgnoreCase(v.toString())){
                table.addData(p, null);;
            }else {
                table.addData(p, v.toString());
            }
        }
        return table;
    }


    /**
     * 删除数据
     * @param paramStr
     * @return
     */
    public static List<TableQuery> parseDelete(String paramStr){
        JSONObject params = JSONObject.parseObject(paramStr);
        //忽略事件
        Boolean ignore = params.containsKey(DirectiveConst.IGNORE);
        List<TableQuery> list = new ArrayList<>();
        params.getJSONArray(DirectiveConst.TAGS).forEach(t->{
            String tableName = t.toString();
            if(!params.containsKey(tableName)){
                return;
            }

            JSONObject tableParam = params.getJSONObject(tableName);
            TableQuery table = new TableQuery();
            table.setTable(tableName);
            table.setIgnore(ignore);

            for(String k:tableParam.keySet()){
                if(DirectiveConst.EXP.equalsIgnoreCase(k)){
                    table.setExps(tableParam.getJSONObject(DirectiveConst.EXP));;
                }else {
                    table.addData(k, tableParam.getString(k));
                }
            }
            list.add(table);
        });

      return list;
    }
}
